﻿#include "HttpServer.h"

#include "TCPServer.h"
#include "TCPClient.h"

#include "Output/Console.h"

#include "HttpIncomingRequest.h"

#include "HttpResponse.h"

CHttpServer::CHttpServer(const SIPAddress &InIP, uint16_t InPort)
{
    Server=CTCPServer::Create();
    Server->Listen(InIP,InPort);
    assert(Server->IsListening());
    
    Server->OnClientConnected.Bind([this]()
    {
        auto Client=Server->GetNextPendingClient();
        AddClient(Client);
    });

}

CHttpServer::~CHttpServer()
{
}

void CHttpServer::AddRoute(const CString &InPath, std::function<std::shared_ptr<CHttpResponse>(std::shared_ptr<CHttpIncomingRequest>)> InFunction)
{
    Routes.Add(InPath,InFunction);
}

std::shared_ptr<CHttpResponse> CHttpServer::RouteRequest(std::shared_ptr<CHttpIncomingRequest> Request)
{
    auto Route=Routes.Find(Request->ResoucePath);
    if(Route)
    {
        return (*Route)(Request);
    }

    //return 404
    return CHttpResponse::NotFoundResponse();
}

void CHttpServer::AddClient(TThreadSafeSharedPtr<CTCPClient> Client)
{
    Clients.Add(Client);
    TThreadSafeWeakPtr<CTCPClient> ClientWeak=Client;
    Client->OnDataReceived.Bind([this,ClientWeak]() mutable
    {
        auto Client=ClientWeak.Lock();
        if(!Client)
        {
            return;
        }

        TVector<uint8_t> StringData = Client->ReadAllData();
        StringData.Add(u8'\0');
        CString String((char8_t*)StringData.Data());

        auto Request = CHttpIncomingRequest::Parse(String);
        if(!Request)
        {
            //parse request failed
            WH::PrintLine(U"解析请求失败");
            WH::PrintLine(String);
            return;
        }
        
        auto Response =RouteRequest(Request);
        CString ResponseString= Response->ToString();
        Client->Send(ResponseString);
    });

    Client->OnDisconnected.Bind([this,ClientWeak]() mutable
    {
        auto Client=ClientWeak.Lock();
        if(!Client)
        {
            return;
        }
        Clients.Remove(Client);
    });


}
